import os
import sys
from datetime import datetime
from typing import List, Dict, Any, Optional
import abc

# Add project root directory to system path
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.abspath(os.path.join(current_dir, "..", ".."))
sys.path.append(project_root)


class Assignable(metaclass=abc.ABCMeta):
    """Abstract base class for assignable tasks"""
    
    @abc.abstractmethod
    def get_details(self) -> str:
        """Get task details"""
        pass
    
    @abc.abstractmethod
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for persistence"""
        pass


class AssignmentSubmission:
    """Assignment submission class"""
    
    def __init__(self, student, assignment, content: str):
        from User.Student import Student
        if not isinstance(student, Student):
            raise TypeError("student must be an instance of Student")
        self.student = student
        self.assignment = assignment
        self.content = content
        self.submitted_at = datetime.now()
        self.grade: Optional[float] = None
        self.feedback: str = ""
        self.graded_by: Optional[str] = None
        self.graded_at: Optional[datetime] = None
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary"""
        return {
            "student_id": self.student.ID,
            "submitted_at": self.submitted_at.strftime("%Y-%m-%d %H:%M:%S"),
            "content": self.content,
            "grade": self.grade,
            "feedback": self.feedback,
            "graded_by": self.graded_by,
            "graded_at": self.graded_at.strftime("%Y-%m-%d %H:%M:%S") if self.graded_at else None
        }


class Assignment(Assignable):
    """Assignment class implementing Assignable abstract interface"""
    
    def __init__(self, ID: str, Title: str, Description: str, Deadline: datetime, course):
        """Initialize assignment"""
        from Course.Course import Course
        self.ID = ID
        self.Title = Title
        self.Description = Description
        self.Deadline = Deadline
        self.Course = course  # Associated course
        self.Submissions: List[AssignmentSubmission] = []  # Student submissions list
    
    def get_details(self) -> str:
        """Get assignment details as string"""
        return (f"Assignment Title: {self.Title}\n"
                f"Description: {self.Description}\n"
                f"Deadline: {self.Deadline.strftime('%Y-%m-%d %H:%M')}\n"
                f"Course: {self.Course.CourseName}")
    
    def submit(self, student, content: str) -> AssignmentSubmission:
        """Submit assignment"""
        from User.Student import Student
        if not isinstance(student, Student):
            raise TypeError("student must be an instance of Student")
        submission = AssignmentSubmission(student, self, content)
        self.Submissions.append(submission)
        return submission
    
    def is_submitted_by(self, student) -> bool:
        """Check if student has submitted this assignment"""
        from User.Student import Student
        if not isinstance(student, Student):
            return False
        return any(s.student.ID == student.ID for s in self.Submissions)
    
    def get_submissions_by_assignment(self, assignment_id: str) -> List[Any]:
        """Get all submissions by assignment ID - new auxiliary method"""
        import json
        try:
            with open(self.data_path, 'r', encoding='utf-8') as f:
                assignment_data_list = json.load(f)
                for assignment_data in assignment_data_list:
                    if assignment_data.get('id') == assignment_id:
                        return assignment_data.get('submissions', [])
            return []
        except Exception as e:
            print(f"Failed to retrieve submissions: {str(e)}")
            return []
    
    def grade_submission(self, student, grade: float, feedback: str, grader_id: str) -> bool:
        """Grade student's submission"""
        submission = self.get_submission_by_student(student)
        if submission:
            submission.grade = grade
            submission.feedback = feedback
            submission.graded_by = grader_id
            submission.graded_at = datetime.now()
            return True
        return False
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for persistence"""
        return {
            "id": self.ID,
            "title": self.Title,
            "description": self.Description,
            "deadline": self.Deadline.strftime("%Y-%m-%d %H:%M:%S"),
            "course_id": self.Course.ID,
            "submissions": [s.to_dict() for s in self.Submissions]
        }